﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System.Collections;
using System.Windows.Forms;

namespace KMClient
{
    public partial class ClientRequest
    {
        int canLoseCount=3;
        string loginKey = "";
        bool heartbeat = false;
        public string HeartbeadtMessage { get; set; }
        public delegate void DLogout();
        public DLogout dLogout;
       // string m_servername = "203.195.168.234";
        string m_servername = "192.168.1.102";
        int m_port = 2000;
        TcpClient m_client;
        StreamReader rs;
        NetworkStream ws;
        Queue sendMessageQueue = new Queue();
        Thread thConnect, thCheck, thHeartbeat;
        string mSplit = "-||||-";
        string rSplit = "-::::-";
        string dataKey = "m29f52gc";
        bool run = false;
        public DateTime endTime;
        public DateTime serverTime;
        public bool canRunScript;
        Dictionary<string, Dictionary<string, string>> returnMsg = new Dictionary<string, Dictionary<string, string>>();
        public  Dictionary<string, string> StringToDictionary(string s)
        {
            Dictionary<string, string> result = new Dictionary<string, string>();
            string[] items = s.Split(new string[] { mSplit }, StringSplitOptions.None);
            foreach (string item in items)
            {
                if (item == "")
                {
                    continue;
                }
                string[] temp = item.Split(new string[] { rSplit }, StringSplitOptions.None);
                result.Add(temp[0], temp[1]);
            }
            return result;
        }
        public string DictionaryToString(Dictionary<string, string> d)
        {
            StringBuilder temp = new StringBuilder();
            foreach (var item in d)
            {
               temp.Append( item.Key + rSplit + item.Value);
               if (d.Count != 0)
               {
                   temp.Append(mSplit);
               }
            }
            return temp.ToString();
        }
      
       
        byte[] EncodingUTF8(string buf)
        {
            byte[] data = Encoding.UTF8.GetBytes(buf + "\r\n");
            return data;
        }
     
        public ClientRequest()
        {
        
            thHeartbeat = new Thread(Heartbeat);
            thHeartbeat.IsBackground = true;
            thHeartbeat.Start();
        }
        /// <summary>
        /// 登录心脏线程
        /// </summary>
        public void Heartbeat()
        {
            while (true)
            {
                if (heartbeat)
                {
                   
                    Dictionary<string, string> msg = new Dictionary<string, string>();
                    msg.Add("login_key", loginKey);
                    msg.Add("msg_key", "Heartbeat");
                    send(msg);
                    Dictionary<string, string> result = GetReturnMsg("Heartbeat");
                    HeartbeadtMessage = result["message"];
                    if (result["status"]=="true")
                    {
                        canLoseCount = 60;
                        endTime = DateTime.Parse(result["end_time"]);
                        serverTime=DateTime.Parse(result["server_time"]);
                        if (endTime < serverTime)
                        {
                            canRunScript = false;
                        }
                        else
                        {
                            canRunScript = true;
                        } 
                    }
                    else
                    {
                        canLoseCount--;
                        if (canLoseCount<0)
                        {
                            heartbeat = false;
                            dLogout();
                        }
                       
                    }
                }
                else
                {
                    canRunScript = false;
                }
                Thread.Sleep(5000);
            }
        }
    
        /// <summary>
        /// 同步
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public void send(Dictionary<string,string> msg)
        {
             string msgString=DictionaryToString(msg);
             msgString= EncryptUtils.Encrypt(msgString, dataKey);
            sendMessageQueue.Enqueue(new KeyValuePair<DateTime,string> (DateTime.Now,msgString));
            Start();
        }
        public void Start()
        {
            run = true;
            if (thCheck == null)
            {
                thCheck = new Thread(CheckConnect);
                thCheck.IsBackground = true;    
                thCheck.Start();
            }
            else if (thCheck.ThreadState != ThreadState.Running)
            {
                thCheck.Abort();
                thCheck = new Thread(CheckConnect);
                thCheck.IsBackground = true;    
                thCheck.Start();
            }
      
        }
        void CheckConnect()
        {
            while (run)
            {
                //监听线程维护
                if (thConnect == null)
                {
                    thConnect = new Thread(Connect);
                    thConnect.IsBackground = true;    
                    thConnect.Start();
                }
                else if (thConnect.ThreadState == ThreadState.Stopped||
                    thConnect.ThreadState == ThreadState.Aborted
                    )
                {
                    m_client.Close();
                    thConnect = new Thread(Connect);
                    thConnect.IsBackground = true;    
                    thConnect.Start();
                }
                //心脏线程维护
                if (thHeartbeat == null)
                {
                    thHeartbeat = new Thread(Heartbeat);
                    thHeartbeat.IsBackground = true;
                    thHeartbeat.Start();
                }
                else if (thHeartbeat.ThreadState == ThreadState.Stopped ||
                    thHeartbeat.ThreadState == ThreadState.Aborted
                    )
                {

                    thHeartbeat = new Thread(Heartbeat);
                    thHeartbeat.IsBackground = true;
                    thHeartbeat.Start();
                }
                Thread.Sleep(2000);
            }
        }
        public void Stop()
        {
            run = false;
        }

        public void Connect()
        {


            try
            {
                m_client = new TcpClient();
                m_client.Connect(m_servername, m_port);
                rs = new StreamReader(m_client.GetStream());
                ws = m_client.GetStream();
                string m_sendData, m_returnData;
                byte[] data;
                while (run)
                {
                    if (sendMessageQueue.Count > 0)
                    {
                        KeyValuePair<DateTime, string> tempdata;
                        lock (sendMessageQueue)
                        {
                            tempdata = (KeyValuePair<DateTime, string>)sendMessageQueue.Dequeue();
                        }
                        if (tempdata.Key < DateTime.Now.AddSeconds(-10))
                        {
                            continue;
                        }
                        m_sendData = tempdata.Value;
                        data = EncodingUTF8(m_sendData);
                        ws.Write(data, 0, data.Length);
                        m_returnData = rs.ReadLine();
                        m_returnData = EncryptUtils.Decrypt(m_returnData, dataKey);
                        Dictionary<string, string> tempD = StringToDictionary(m_returnData);
                        string tempkey = tempD["msg_key"];
                        tempD.Remove(tempkey);
                        returnMsg.Add(tempkey, tempD);
                    }
                    Thread.Sleep(300);
                }
                run = false;

            }
            catch (Exception e)
            {
                m_client.Close();
             //   MessageBox.Show(e.Message + "zhekkdfaslkdfj");
                return;
            }
            run = false;
            return;
        }
      
        public Dictionary<string, string> GetReturnMsg(string key)
        {
            Dictionary<string, string> r = new Dictionary<string, string>();
            int i = 10;
            while (!returnMsg.ContainsKey(key))
            {
                Thread.Sleep(1000);
                i--;
                if (i==0)
                {
                    r.Add("status","false");
                    r.Add("message", "请求超时");
                    return r;
                }
            }
            r=returnMsg[key];
            returnMsg.Remove(key);
            return r;
        }
       
        public Dictionary<string,string> Register(string username,string password)
        {
            Dictionary<string, string> msg = new Dictionary<string, string>();
            msg.Add("username",username);
            msg.Add("password", password);
            msg.Add("script_id","1");
            msg.Add("msg_key", "Register");
            send(msg);
            return GetReturnMsg("Register");
        }

        internal Dictionary<string, string> Login(string username, string password)
        {
            Dictionary<string, string> msg = new Dictionary<string, string>();
            msg.Add("username", username);
            msg.Add("password", password);
            msg.Add("script_id", "1");
            msg.Add("msg_key", "Login");
            msg.Add("version", System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString());
            send(msg);
            var tempResult = GetReturnMsg("Login");
            if (tempResult["status"]=="true")
            {
                loginKey = tempResult["login_key"];
                heartbeat = true;
            }
            return tempResult;
        }

        internal Dictionary<string, string> ResetPassword(string oldPassword, string newPassword)
        {
            Dictionary<string, string> msg = new Dictionary<string, string>();
            msg.Add("old_password", oldPassword);
            msg.Add("new_password", newPassword);
            msg.Add("login_key",loginKey);
            msg.Add("msg_key", "ResetPassword");
            send(msg);
            return GetReturnMsg("ResetPassword");
        }

        internal Dictionary<string, string> Recharge(string cdkey)
        {
            Dictionary<string, string> msg = new Dictionary<string, string>();
            msg.Add("cdkey", cdkey);
            msg.Add("login_key", loginKey);
            msg.Add("msg_key", "Recharge");
            send(msg);
            return GetReturnMsg("Recharge");
            var tempResult = GetReturnMsg("Recharge");
            if (tempResult["status"] == "true")
            {
                canRunScript = true;
            }
            return tempResult;
        }
        public void Logout()
        {

            this.canRunScript = false;
            Dictionary<string, string> msg = new Dictionary<string, string>();
            msg.Add("login_key", loginKey);
            msg.Add("msg_key", "Logout");
            send(msg);
        }
    }
}
